feat(shader-driver): wire CypherBridge — lg.cypher step_type now routes#258
Conversation
Adds CypherBridge as an OrchestrationBridge implementation for the `lg.cypher` step_type, closing the "domain unavailable and planner not compiled in" gap on /v1/shader/route. Phase 1 (this commit): lightweight prefix classifier that maps - CREATE (...) → StepStatus::Completed, confidence 0.5 - MATCH (...) RETURN ... → StepStatus::Completed, confidence 0.5 - anything else → StepStatus::Skipped (stub-in-place) - non-lg.cypher step_type → Err(DomainUnavailable) so route_handler falls through to the planner bridge as before. Phase 2 (deferred): wire the real lance_graph::parser::parse_cypher_query + SPO commit / BindSpace label search. Pulling the lance-graph core dep (arrow + datafusion + lance) into cognitive-shader-driver would balloon build time for what today is a test-path transport; Phase 2 arrives once the SPO store handle is actually consumed downstream. route_handler in serve.rs is now a three-stage chain: CodecResearchBridge (nd.*) → CypherBridge (lg.cypher) → planner_bridge. Each stage falls through only on DomainUnavailable, so execution failures inside a stage still surface to the client unchanged. Tests: 7 new unit tests in cypher_bridge.rs (create, match, unsupported, non-cypher, missing-reasoning, lowercase, nd-reject). Live-verified via curl against localhost:3001/v1/shader/route for all four cases. https://claude.ai/code/session_01SbYsmmbPf9YQuYbHZN52Zh
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: b56f7d4199
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| let preview_len = 50.min(query.len()); | ||
| step.reasoning = Some(format!( | ||
| "unsupported cypher construct, stub in place: {}", | ||
| &query[..preview_len] | ||
| )); |
There was a problem hiding this comment.
Avoid byte slicing when truncating unsupported query preview
The unsupported-Cypher path truncates with &query[..preview_len] where preview_len is a byte count (50.min(query.len())). For queries longer than 50 bytes that contain multibyte UTF-8 characters, this can cut through a code point and panic at runtime, turning a normal lg.cypher request into a server error. Please switch to a char-boundary-safe truncation method before building the preview string.
Useful? React with 👍 / 👎.
| if matches!( | ||
| cypher_result, | ||
| Err(lance_graph_contract::orchestration::OrchestrationError::DomainUnavailable(_)) | ||
| ) { |
There was a problem hiding this comment.
Handle non-domain Cypher routing errors in route handler
After invoking CypherBridge, the handler only checks for DomainUnavailable and ignores RoutingFailed/ExecutionFailed. For invalid lg.cypher inputs (for example, missing reasoning), this leaves the request in a non-terminal state because the bridge error is dropped, and clients can receive running instead of a clear failure. Please explicitly handle non-domain errors from cypher_result as failed responses (or propagate them).
Useful? React with 👍 / 👎.
Summary
CypherBridge(crates/cognitive-shader-driver/src/cypher_bridge.rs), anOrchestrationBridgeimpl that claimslg.cypherstep_types and keeps every otherlg.*/nd.*/ non-lance-graph step flowing to its existing bridge.route_handlerinserve.rsas the middle stage of a three-stage chain:CodecResearchBridge(nd.) →CypherBridge(lg.cypher) →planner_bridge(lg. residual, feature-gated).CREATEandMATCH→StepStatus::Completed+ confidence 0.5 with a "stub — actual SPO commit / BindSpace search pending" reasoning; anything else cypher-shaped →StepStatus::Skipped; non-lg.cypher→Err(DomainUnavailable)so the handler falls through unchanged.Phase 2 (real
lance_graph::parser::parse_cypher_query+ SPO commit + BindSpace label search) is deliberately deferred: pulling lance-graph core (arrow + datafusion + lance) into cognitive-shader-driver would balloon build time for what today is a test-path transport. The statelessCypherBridgestruct is explicitly shaped so an SPO store handle slots in when Phase 2 lands.Closes the
{"status":"failed","reasoning":"domain unavailable and planner not compiled in"}hole on/v1/shader/routeforlg.cypher.Test plan
cargo test --manifest-path crates/cognitive-shader-driver/Cargo.toml --features serve --lib cypher_bridge— 7 new unit tests pass:create_cypher_parses,match_cypher_parses,unsupported_cypher_skipped,non_cypher_rejected,missing_reasoning_errors,lowercase_cypher_parses,nd_prefix_rejected.localhost:3001/v1/shader/routewithshader-serve --features serve:CREATE (p:Palantir {id:1})→{"status":"completed","reasoning":"cypher CREATE parsed (stub — actual SPO commit pending)","confidence":0.5}MATCH (c:Customer) RETURN c→{"status":"completed","reasoning":"cypher MATCH parsed (stub — actual BindSpace search pending)","confidence":0.5}DROP INDEX foo→{"status":"skipped","reasoning":"unsupported cypher construct, stub in place: DROP INDEX foo"}step_type:"lg.plan"→{"status":"failed","reasoning":"domain unavailable and planner not compiled in"}(unchanged pre-PR behaviour, confirms non-cypherlg.*still falls through).lance-graph = { path = "../lance-graph", optional = true }under awith-cypherfeature and wireparse_cypher_query+ SPO commit once theCypherBridgehas an actual SPO store handle to commit against.https://claude.ai/code/session_01SbYsmmbPf9YQuYbHZN52Zh
Generated by Claude Code